package com.white.mybatis.dynamic.support.proxy;

import com.white.mybatis.dynamic.support.proxy.utils.ClassUtils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

public abstract class AbstractProxy<T,R> implements Aspectj , Function<T,R> {

    @Override
    public R apply(T t) {
        if (t == null) {
            return null;
        }
        //对jdk动态代理进行增强
        List<Class<?>> classes = new ArrayList<>(Arrays.asList(ClassUtils.getAllInterface(t.getClass())));
        classes.add(TargetClassAware.class);
        return (R) LegendCglibProxy.newProxyInstance(t.getClass().getClassLoader(),
                t.getClass(),
                classes.toArray(new Class[0]),
                getInvocationHandler(t));
    }

    /**
     * 代理处理器
     * @param t 源对象
     * @return
     */
    protected InvocationHandler getInvocationHandler(T t){
        return (proxy, method, args) -> {
            //存储源对象
            if ("getTargetClass".equals(method.getName()) && method.getParameterCount() == 0) {
                return t.getClass();
            }
            if ("getTarget".equals(method.getName()) && method.getParameterCount() == 0) {
                return t;
            }

            try {
                //前置
                enhance(t,method,args);
                //执行原有方法
                Object result = method.invoke(t,args);
                //后置
                return postposition(t,method,args,result);
            } catch (InvocationTargetException e) {
                //异常处理器
                return exceptionHandle(t,method,args,e.getCause());
            } catch (Throwable e) {
                //异常处理器
                return exceptionHandle(t,method,args,e);
            }
        };
    }
}
